﻿#!/usr/bin/env python3

import socket
import select
import queue
import sys

def main():
    '''echo 'select' server -'''
    print(main.__doc__)
    print("="*30)

    HOST = 'localhost'                 # Symbolic name meaning all available interfaces
    PORT = 1000              # Arbitrary non-privileged port
    saddr = (HOST, PORT)
    
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.setblocking(0)

    print("Start up on localhost:1000")
    server.bind(saddr)
    server.listen(3)        # 3 backlog

    inputs=[server]
    outputs = []
    msgqueue = {}

    while inputs:
        print('waiting....')
        timeout = 5
        rlist, wlist, exceptlist = select.select(inputs, outputs, inputs, timeout)

        if not(rlist or wlist or exceptlist):
            print('timeout ...')
            break

        #input list
        for s in rlist:
            if s is server:
                #.相应请求, 创建新连接
                conn, clientaddr = s.accept()
                conn.setblocking(0)
                print('conn from ', clientaddr)
                inputs.append(conn)

                msgqueue[conn] = queue.Queue()
            else:
                #接收数据
                data = s.recv(1024)
                if data:
                    print('  recv {!r} from {}'.format(data, s.getpeername()))
                    #准备发回
                    msgqueue[s].put(data)   
                    if s not in outputs:
                        outputs.append(s)
                else:
                    #close
                    print('  close', s.getpeername())
                    if s in outputs:
                        outputs.remove(s)
                    inputs.remove(s)

                    s.close()
                    del msgqueue[s]


        #output list
        for s in wlist:
            #print('wlist length = {}'.format(len(wlist)))            
            #print('  s = {}'.format(s.getpeername()))
            try:
                nextmsg = msgqueue[s].get_nowait()
            except queue.Empty:
                print(s.getpeername(), 'queue is empty')
                outputs.remove(s)
            else:
                print('  sending {!r} to {}'.format(nextmsg, s.getpeername()))
                s.send(nextmsg)

        #exception list
        for s in exceptlist:
            print('exception on', s.getpeername())
            inputs.remove(s)
            if s in outputs:
                outputs.remove(s)
            s.close()

            del msgqueue[s]


if __name__=='__main__':
    main()
